package com.lancoo.ccas52.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lancoo.ccas52.entity.*;
import com.lancoo.ccas52.exception.BizException;
import com.lancoo.ccas52.mapper.*;
import com.lancoo.ccas52.pojo.common.GroupObject;
import com.lancoo.ccas52.pojo.common.PageInfo;
import com.lancoo.ccas52.pojo.vo.*;
import com.lancoo.ccas52.service.*;
import com.lancoo.ccas52.util.ExcelFormatUtil;
import com.lancoo.ccas52.util.PagingUtil;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Component
public class BasicRuleServiceImpl implements BasicRuleService {

    @Resource
    @Lazy
    private TeachingClassService teachingClassService;
    @Resource
    private TeacherService teacherService;
    @Resource
    private RoomService roomService;
    @Resource
    private TeachingClassMapper teachingClassMapper;

    @Resource
    private RuleUsableMapper ruleUsableMapper;
    @Resource
    private MajorService majorService;
    @Resource
    private PeriodSchemeMapper periodSchemeMapper;
    @Resource
    private RuleWeekDayService ruleWeekDayService;
    @Resource
    private RuleTimeProhibitService ruleTimeProhibitService;
    @Resource
    private RuleRoomProhibitService ruleRoomProhibitService;
    @Resource
    private RuleCourseProhibitService ruleCourseProhibitService;
    @Resource
    private RuleTeacherTimeService ruleTeacherTimeService;
    @Resource
    private RuleTeacherSettingService ruleTeacherSettingService;
    @Resource
    private CollegeRoomService collegeRoomService;
    @Resource
    private TeacherMapper teacherMapper;
    @Resource
    private MajorMapper majorMapper;

    @Override
    public CampusCrossGetResponse getMajor(Integer taskId, String collegeId, String majorId, String gradeId, String keyword, String campusId, Integer currentPage, Integer pageSize) {
        List<Major> majorList = majorService.lambdaQuery().eq(Major::getTaskId, taskId)
                .eq(StrUtil.isNotBlank(collegeId), Major::getCollegeId, collegeId)
                .eq(StrUtil.isNotBlank(majorId), Major::getBaseMajorId, majorId)
                .eq(StrUtil.isNotBlank(gradeId), Major::getGradeId, gradeId)
                .eq(StrUtil.isNotBlank(campusId), Major::getCampusId, campusId)
                .and(StrUtil.isNotBlank(keyword), wrapper -> wrapper.like(Major::getMajorName, keyword).or().like(Major::getCollegeName, keyword))
                .list();
        PageInfo<Major> majorPage = PagingUtil.getPages(currentPage, pageSize, majorList);
        long collegeNum = majorList.stream().map(Major::getCollegeId).distinct().count();
        long gradeNum = majorList.stream().map(Major::getGradeId).distinct().count();
        long majorNum = majorList.stream().map(Major::getBaseMajorId).distinct().count();

        return CampusCrossGetResponse.builder()
                .facultyMajorList(majorPage.getList())
                .totalCollege(collegeNum)
                .totalGrade(gradeNum)
                .totalMajor(majorNum)
                .currentPage(majorPage.getCurrentPage())
                .pageSize(majorPage.getPageSize())
                .total(majorPage.getTotal())
                .build();

    }

    @Override
    public boolean setCampus(List<Long> majorIds, String campusId, String campusName) {
        boolean update = majorService.lambdaUpdate().set(Major::getCampusId, campusId)
                .set(Major::getCampusName, campusName)
                .in(CollUtil.isNotEmpty(majorIds), Major::getMajorId, majorIds).update();
        return update;
    }

    @Override
    public List<CollegeRoomVo> getCollegeRoom(Integer taskId, String collegeId, String keyword) {
        List<CollegeDto> collegeDtoList = majorMapper.getCollegeByTaskId(taskId);
        if (StrUtil.isNotBlank(keyword)) {
            collegeDtoList = collegeDtoList.stream()
                    .filter(collegeDto -> collegeDto.getCollegeName().contains(keyword)).collect(Collectors.toList());
        }
        if (StrUtil.isNotBlank(collegeId)) {
            collegeDtoList = collegeDtoList.stream()
                    .filter(collegeDto -> collegeDto.getCollegeId().equals(collegeId)).collect(Collectors.toList());
        }
        List<CollegeRoomVo> collegeRoomVoList = BeanUtil.copyToList(collegeDtoList, CollegeRoomVo.class);
        if (CollUtil.isNotEmpty(collegeRoomVoList)) {
            //添加上课场地
            List<String> collegeIds = collegeRoomVoList.stream().map(CollegeRoomVo::getCollegeId).collect(Collectors.toList());
            collegeRoomService.lambdaQuery().eq(CollegeRoom::getTaskId, taskId).in(CollegeRoom::getCollegeId, collegeIds).list().
                    stream().collect(Collectors.groupingBy(CollegeRoom::getCollegeId)).forEach((k, v) -> {
                        collegeRoomVoList.forEach(collegeRoomVo -> {
                            if (collegeRoomVo.getCollegeId().equals(k)) {
                                collegeRoomVo.setCollegeRooms(v);
                            }
                        });
                    });
        }
        return collegeRoomVoList;
    }

    @Override
    public Boolean setCollegeRoom(CollegeRoomInput collegeRoomInput) {
        //删除原有的
        collegeRoomService.lambdaUpdate().eq(CollegeRoom::getTaskId, collegeRoomInput.getTaskId())
                .in(CollegeRoom::getCollegeId, collegeRoomInput.getCollegeIds()).remove();
        //添加新的
        collegeRoomService.saveBatch(collegeRoomInput.getCollegeRooms());
        return true;

    }


    @Override
    public List<PeriodSchemeGroupVo> getPeriodSchemes(String schoolId, String term) {
        List<PeriodSchemeGroupVo> schemeList = new ArrayList<>();
        List<PeriodScheme> periodSchemes = periodSchemeMapper.selectList(new LambdaQueryWrapper<PeriodScheme>()
                .eq(PeriodScheme::getSchoolId, schoolId).eq(PeriodScheme::getTerm, term));
        //分组
        Map<String, List<PeriodScheme>> periodMap = periodSchemes.stream().collect(Collectors.groupingBy(PeriodScheme::getBaseSchemeId));
        periodMap.forEach((key, value) -> {
            schemeList.add(PeriodSchemeGroupVo.builder()
                    .baseSchemeId(key)
                    .baseSchemeName(value.get(0).getBaseSchemeName())
                    .periodSchemes(value).build());
        });
        return schemeList;
    }

    @Override
    public List<RuleWeekDay> getWeekDays(String schoolId, String term) {
        List<RuleWeekDay> weekDays = ruleWeekDayService.lambdaQuery().eq(RuleWeekDay::getSchoolId, schoolId).eq(RuleWeekDay::getTerm, term).list();
        //填充节次信息
        List<PeriodScheme> periodSchemes = periodSchemeMapper.selectList(new LambdaQueryWrapper<PeriodScheme>()
                .eq(PeriodScheme::getSchoolId, schoolId).eq(PeriodScheme::getTerm, term));
        //分组
        Map<String, List<PeriodScheme>> periodMap = periodSchemes.stream().collect(Collectors.groupingBy(PeriodScheme::getBaseSchemeId));
        weekDays.forEach(day -> {
            day.setPeriodSchemes(periodMap.get(day.getBaseSchemeId()));
        });
        return weekDays;
    }


    @Override
    public Boolean updateWeekDay(Integer taskId, List<RuleWeekDay> weekDays) {
        ruleWeekDayService.lambdaUpdate().eq(RuleWeekDay::getTaskId, taskId).remove();
        if (weekDays.size() > 0) {
            ruleWeekDayService.saveBatch(weekDays);
        }
        return true;
    }


    @Override
    public MaxPeriodScheme getMaxPeriodScheme(String schoolId, String term) {
        List<RuleWeekDay> weekDays = this.getWeekDays(schoolId, term);
        if (weekDays.size() == 0) {
            return null;
        }
        //判断是统一设置还是单日设置
        boolean flag = weekDays.stream()
                .map(RuleWeekDay::getBaseSchemeId)
                .allMatch(value -> value.equals(weekDays.get(0).getBaseSchemeId()));

        List<PeriodScheme> periodSchemes;
        periodSchemes = weekDays.stream().max(Comparator.comparing(g -> g.getPeriodSchemes().size())).get().getPeriodSchemes();
        return MaxPeriodScheme.builder().isUniformly(flag).periodSchemes(periodSchemes).build();
    }


    @Override
    public void initWeekDays(Integer taskId, Integer weekSet, String schoolId, String term, List<PeriodScheme> periodSchemes) {
        //先判断是否已经设置过了
        boolean exists = ruleWeekDayService.lambdaQuery().eq(RuleWeekDay::getSchoolId, schoolId)
                .eq(RuleWeekDay::getTerm, term)
                .exists();
        if (exists) {
            return;
        }
        if (CollUtil.isNotEmpty(periodSchemes)) {
            List<RuleWeekDay> weekDays = new ArrayList<>();
            PeriodScheme periodScheme = periodSchemes.stream().findFirst().get();
            for (int i = 1; i <= 5; i++) {
                RuleWeekDay ruleWeekDay = new RuleWeekDay();
                weekDays.add(ruleWeekDay.setTaskId(taskId)
                        .setBaseSchemeId(periodScheme.getBaseSchemeId())
                        .setBaseSchemeName(periodScheme.getBaseSchemeName())
                        .setSchoolId(schoolId)
                        .setTerm(term)
                        .setWeekDayCode(String.format("%02d", i)));
            }
            if (weekSet.equals(1)) {
                for (int i = 8; i <= 12; i++) {
                    RuleWeekDay ruleWeekDay = new RuleWeekDay();
                    weekDays.add(ruleWeekDay.setTaskId(taskId)
                            .setBaseSchemeId(periodScheme.getBaseSchemeId())
                            .setBaseSchemeName(periodScheme.getBaseSchemeName())
                            .setSchoolId(schoolId)
                            .setTerm(term)
                            .setWeekDayCode(String.format("%02d", i)));
                }
            }
            ruleWeekDayService.saveBatch(weekDays);
        }
    }

    @Override
    public void initRuleUsable(Integer taskId, String schoolId, String term) {
        List<RuleUsable> usableList = new ArrayList<>();
        for (int i = 9; i <= 11; i++) {
            RuleUsable ruleUsable = new RuleUsable();
            usableList.add(ruleUsable.setTaskId(taskId)
                    .setSchoolId(schoolId)
                    .setTerm(term)
                    .setCode(i)
                    .setOption("a"));
        }
        ruleUsableMapper.addBatch(usableList);
        //学校学期共享数据 课时方案统一设置
        Long count = ruleUsableMapper.selectCount(new LambdaQueryWrapper<RuleUsable>()
                .eq(RuleUsable::getSchoolId, schoolId).eq(RuleUsable::getTerm, term).eq(RuleUsable::getCode, 8));
        if (count == 0) {
            ruleUsableMapper.addBatch(Collections.singletonList(new RuleUsable().setTaskId(taskId)
                    .setSchoolId(schoolId)
                    .setTerm(term)
                    .setCode(8)
                    .setOption("a")));
        }
        //初始化教师统一设置
        ruleTeacherSettingService.save(new RuleTeacherSetting().setTaskId(taskId).setMaxSection(4));
    }

    @Override
    public void setBasicRule(SetBasciRuleRequest setBasciRuleRequest) {
        ruleUsableMapper.setBasicRule(setBasciRuleRequest.getRules(), setBasciRuleRequest.getTaskId());
    }

    @Override
    public List<RuleUsable> getCurrent(Integer taskId, String schoolId, String term, String collegeId) {
        List<RuleUsable> bySchoolTerm = ruleUsableMapper.getBySchoolTerm(schoolId, term, collegeId);
        //没有设置的规则，动态赋值
        for (int i = 9; i <= 11; i++) {
            int finalI = i;
            Optional<RuleUsable> oneRule = bySchoolTerm.stream().filter(ruleUsable -> ruleUsable.getCode().equals(finalI)).findFirst();
            if (!oneRule.isPresent()) {
                RuleUsable ruleUsable = new RuleUsable();
                bySchoolTerm.add(ruleUsable.setTaskId(taskId)
                        .setSchoolId(schoolId)
                        .setTerm(term)
                        .setCode(i)
                        .setOption("a"));
            }
        }
        return bySchoolTerm;
    }

    @Override
    public List<RuleTimeProhibit> getTimeProhibit(String schoolId, String term, String collegeId) {
        List<RuleTimeProhibit> timeProhibits = new ArrayList<>();
        if (ObjUtil.isNull(collegeId)) {
            return timeProhibits;
        }
        timeProhibits = ruleTimeProhibitService.lambdaQuery()
                .eq(RuleTimeProhibit::getSchoolId, schoolId).eq(RuleTimeProhibit::getTerm, term)
                .eq(RuleTimeProhibit::getCollegeId, collegeId).list();
        return timeProhibits;

    }

    @Override
    public boolean setTimeProhibit(Integer taskId, String collegeId, List<RuleTimeProhibit> ruleTimeProhibits) {
        //删除原有的禁排规则
        ruleTimeProhibitService.lambdaUpdate().eq(RuleTimeProhibit::getTaskId, taskId).eq(RuleTimeProhibit::getCollegeId, collegeId).remove();
        ruleTimeProhibitService.saveBatch(ruleTimeProhibits);
        return true;

    }

    @Override
    public List<RuleRoomProhibit> getRoomProhibit(String schoolId, String term, String collegeId, Long roomId) {
        List<RuleRoomProhibit> roomProhibits = ruleRoomProhibitService.lambdaQuery().eq(RuleRoomProhibit::getSchoolId, schoolId)
                .eq(RuleRoomProhibit::getTerm, term)
                .eq(RuleRoomProhibit::getRoomId, roomId)
                .eq(RuleRoomProhibit::getCollegeId, collegeId).list();
        return roomProhibits;
    }

    @Override
    public boolean setRoomProhibit(Integer taskId, String collegeId, List<RuleRoomProhibit> ruleRoomProhibits, List<Long> roomIds) {
        //删除原有的禁排规则
        if (CollUtil.isNotEmpty(roomIds)) {
            ruleRoomProhibitService.lambdaUpdate().in(RuleRoomProhibit::getRoomId, roomIds).eq(RuleRoomProhibit::getTaskId, taskId).eq(RuleRoomProhibit::getCollegeId, collegeId).remove();
        }
        boolean b = ruleRoomProhibitService.saveBatch(ruleRoomProhibits);
        return true;
    }

    @Override
    public boolean removeRoomProhibitByIds(Integer taskId, String collegeId, List<Long> ids) {
        ruleRoomProhibitService.lambdaUpdate().in(RuleRoomProhibit::getRoomId, ids)
                .eq(RuleRoomProhibit::getTaskId, taskId).eq(RuleRoomProhibit::getCollegeId, collegeId).remove();
        return true;
    }

    @Override
    public PageInfo<RuleTeachingClassVo> getTeachingClassProhibit(Integer taskId, IPage page, String courseTypeId, Integer courseNature, Integer majorProp, String collegeId, String keyWord, Integer state) {
        PageInfo<RuleTeachingClassVo> simpleTeachingClass = teachingClassService.getSimpleTeachingClass(taskId, page, courseTypeId, courseNature, majorProp, collegeId, keyWord, state);
        List<Long> teachingClassIds = simpleTeachingClass.getList().stream().map(RuleTeachingClassVo::getTeachingClassId).collect(Collectors.toList());
        if (teachingClassIds.size() > 0) {
            Map<Long, List<RuleCourseProhibit>> ruleMap = ruleCourseProhibitService.lambdaQuery().eq(RuleCourseProhibit::getTaskId, taskId)
                    .in(RuleCourseProhibit::getTeachingClassId, teachingClassIds).list()
                    .stream().collect(Collectors.groupingBy(RuleCourseProhibit::getTeachingClassId));
            simpleTeachingClass.getList().forEach(teachingClass -> {
                teachingClass.setRuleCourseProhibits(ruleMap.get(teachingClass.getTeachingClassId()));
            });
        }
        return simpleTeachingClass;
    }

    @Override
    public boolean setTeachingClassProhibit(List<RuleCourseProhibit> ruleCourseProhibits, List<Long> teachingClassIds) {
        //删除原有的禁排规则
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            ruleCourseProhibitService.lambdaUpdate().in(RuleCourseProhibit::getTeachingClassId, teachingClassIds).remove();
        }
        boolean b = ruleCourseProhibitService.saveBatch(ruleCourseProhibits);
        return true;
    }

    @Override
    public boolean removeTeachingClassProhibitByIds(List<Long> ids) {
        ruleCourseProhibitService.lambdaUpdate().in(RuleCourseProhibit::getTeachingClassId, ids).remove();
        return true;
    }


    @Override
    public PageInfo<Teacher> getTeacherList(Page page, Integer taskId, String schoolId, String term, String collegeId, String keyWord, Integer state) {
        IPage<Teacher> teacherPage = teacherMapper.getRuleTeacher(page, schoolId, term, collegeId, keyWord, state);
        List<Long> teacherIds = teacherPage.getRecords().stream().map(Teacher::getTeacherId).collect(Collectors.toList());
        //禁排时间
        if (teacherIds.size() > 0) {
            Map<Long, List<RuleTeacherTime>> ruleMap = ruleTeacherTimeService.lambdaQuery().eq(RuleTeacherTime::getSchoolId, schoolId).eq(RuleTeacherTime::getTerm, term)
                    .in(RuleTeacherTime::getTeacherId, teacherIds).list()
                    .stream().collect(Collectors.groupingBy(RuleTeacherTime::getTeacherId));
            teacherPage.getRecords().forEach(teacher -> {
                teacher.setRuleTeacherTimes(ruleMap.get(teacher.getTeacherId()));
            });

        }
        return PagingUtil.formatPageResult(teacherPage);
    }

    @Override
    public boolean setTeacherTimeProhibit(Integer taskId, String collegeId, Long teacherId, List<RuleTeacherTime> ruleTeacherTimes) {
        //删除原有的禁排规则
        List<Long> teacherIds = ListUtil.toList(teacherId);
        if (CollUtil.isNotEmpty(teacherIds)) {
            ruleTeacherTimeService.lambdaUpdate().in(RuleTeacherTime::getTeacherId, teacherIds).eq(RuleTeacherTime::getTaskId, taskId).eq(RuleTeacherTime::getCollegeId, collegeId).remove();
        }
        boolean b = ruleTeacherTimeService.saveBatch(ruleTeacherTimes);
        return true;
    }

    @Override
    public boolean removeTeacherTimeProhibitByIds(Integer taskId, String collegeId, List<Long> ids) {
        ruleTeacherTimeService.lambdaUpdate().in(RuleTeacherTime::getTeacherId, ids).eq(RuleTeacherTime::getTaskId, taskId).eq(RuleTeacherTime::getCollegeId, collegeId).remove();
        return true;
    }


    @Override
    public RuleTeacherSetting getTeacherSetting(Integer taskId, String collegeId) {
        RuleTeacherSetting ruleTeacherSetting = ruleTeacherSettingService.lambdaQuery()
                .eq(RuleTeacherSetting::getTaskId, taskId).eq(RuleTeacherSetting::getCollegeId, collegeId).one();
        if (ObjUtil.isNull(ruleTeacherSetting)) {
            ruleTeacherSetting = new RuleTeacherSetting();
            ruleTeacherSetting.setTaskId(taskId)
                    .setCollegeId(collegeId)
                    .setIsUniform(1)
                    .setUniformDay(0)
                    .setUniformWeek(0)
                    .setMaxSection(4)
                    .setCampusInterval(1.0);
        }
        return ruleTeacherSetting;
    }

    @Override
    public Boolean setTeacherSetting(RuleTeacherSetting ruleTeacherSetting) {
        return ruleTeacherSettingService.saveOrUpdate(ruleTeacherSetting);
    }

    @Override
    public void removeAllRule(List<Integer> taskIds) {
        ruleCourseProhibitService.lambdaUpdate().in(RuleCourseProhibit::getTaskId, taskIds).remove();
        ruleRoomProhibitService.lambdaUpdate().in(RuleRoomProhibit::getTaskId, taskIds).remove();
        ruleTeacherTimeService.lambdaUpdate().in(RuleTeacherTime::getTaskId, taskIds).remove();
//        ruleUsableMapper.delete(new QueryWrapper<RuleUsable>().in("task_id", taskIds));
//        ruleWeekDayService.lambdaUpdate().in(RuleWeekDay::getTaskId, taskIds).remove();
        ruleTimeProhibitService.lambdaUpdate().in(RuleTimeProhibit::getTaskId, taskIds).remove();
        ruleTeacherSettingService.lambdaUpdate().in(RuleTeacherSetting::getTaskId, taskIds).remove();
    }

    @Override
    public boolean excelToProhibit(ImportProhibit importProhibit, MultipartFile file) {

        try {
            InputStream inputStream = file.getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream);
            List<Map<String, Object>> read = reader.read(2, 3, reader.getRowCount());
            if (CollUtil.isEmpty(read)) {
                throw new BizException(5, "导入文件数据为空");
            }
            if (importProhibit.getMark() == 1) {
                toRoomProhibit(importProhibit, read);
            }
            if (importProhibit.getMark() == 2) {
                toTeachingClassProhibit(importProhibit, read);
            }
            if (importProhibit.getMark() == 3) {
                toTeacherProhibit(importProhibit, read);
            }
            if (importProhibit.getMark() == 4) {
                toTimeProhibit(importProhibit, read);
            }
            if (importProhibit.getMark() == 5) {
                toCollegeRoom(importProhibit, read);
            }
            reader.close();
        } catch (IOException e) {
            throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
        }
        return true;

    }

    /**
     * 时间禁排
     *
     * @param importProhibit
     * @param read
     */
    public void toTimeProhibit(ImportProhibit importProhibit, List<Map<String, Object>> read) {
        List<String> titleList = Arrays.asList("禁排时间");
        List<RuleTimeProhibit> ruleTimeProhibits = new ArrayList<>();

        //判断模块是否符合要求
        boolean allColumnsMatch = titleList.containsAll(read.get(0).keySet());
        if (!allColumnsMatch) {
            throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
        }

        //获取timeCode正则表达式
        String timeCodePattern = getTimeCodePattern(importProhibit.getSchoolId(), importProhibit.getTerm());

        //遍历
        for (int i = 0; i < read.size(); i++) {
            Map<String, Object> map = read.get(i);
            String timeCodes = map.get("禁排时间").toString();

            if (StrUtil.isNotBlank(timeCodes)) {
                String[] split = timeCodes.split("/");
                for (String timeCode : split) {
                    if (!Pattern.matches(timeCodePattern, timeCode)) {
                        throw new BizException(5, ("第" + (i + 4) + "排禁排时间" + timeCode + "超出课时方案"));
                    }
                    ruleTimeProhibits.add(new RuleTimeProhibit()
                            .setTimeCode(timeCode)
                            .setTaskId(importProhibit.getTaskId())
                            .setSchoolId(importProhibit.getSchoolId())
                            .setTerm(importProhibit.getTerm())
                            .setCollegeId(importProhibit.getCollegeId()));
                }
            }
        }

        if (importProhibit.getIsCoverage()) {
            ruleTimeProhibitService.lambdaUpdate().eq(RuleTimeProhibit::getTaskId, importProhibit.getTaskId()).eq(RuleTimeProhibit::getCollegeId,importProhibit.getCollegeId()).remove();
            ruleTimeProhibits = ruleTimeProhibits.stream().distinct().collect(Collectors.toList());
        } else {
            List<RuleTimeProhibit> existProhibit = ruleTimeProhibitService.lambdaQuery().eq(RuleTimeProhibit::getTaskId, importProhibit.getTaskId()).eq(RuleTimeProhibit::getCollegeId,importProhibit.getCollegeId()).list();
            ruleTimeProhibits = ruleTimeProhibits.stream()
                    .filter(o -> existProhibit.stream().noneMatch(e -> e.getTimeCode().equals(o.getTimeCode())))
                    .collect(Collectors.toList());
        }

        if (CollUtil.isNotEmpty(ruleTimeProhibits)) {
            ruleTimeProhibitService.saveBatch(ruleTimeProhibits);
        }
    }


    /**
     * 导入教室禁排
     *
     * @param importProhibit
     * @param read
     */
    public void toRoomProhibit(ImportProhibit importProhibit, List<Map<String, Object>> read) {
        Map<String, Long> roomMap = new HashMap<>();
        List<String> titleList = Arrays.asList("教室名", "禁排时间");
        List<RuleRoomProhibit> ruleRoomProhibits = new ArrayList<>();

        //判断模块是否符合要求
        boolean allColumnsMatch = titleList.containsAll(read.get(0).keySet());
        if (!allColumnsMatch) {
            throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
        }

        //获取全部教室名
        List<String> roomNames = read.stream()
                .map(o -> o.get("教室名").toString())
                .distinct().collect(Collectors.toList());
        //获取全部教室
        if (CollUtil.isNotEmpty(roomNames)) {
            roomMap = roomService.lambdaQuery().eq(Room::getSchoolId, importProhibit.getSchoolId())
                    .eq(Room::getTerm, importProhibit.getTerm()).in(Room::getRoomName, roomNames).list()
                    .stream().collect(Collectors.toMap(Room::getRoomName, Room::getRoomId));
        }
        //获取timeCode正则表达式
        String timeCodePattern = getTimeCodePattern(importProhibit.getSchoolId(), importProhibit.getTerm());

        //遍历
        for (int i = 0; i < read.size(); i++) {
            Map<String, Object> roomProhibit = read.get(i);
            String roomName = roomProhibit.get("教室名").toString();
            String timeCodes = roomProhibit.get("禁排时间").toString();

            if (!roomMap.containsKey(roomName)) {
                throw new BizException(5, ("第" + (i + 4) + "行教室名不存在" + roomName));
            }
            if (StrUtil.isNotBlank(timeCodes)) {
                String[] split = timeCodes.split("/");
                for (String timeCode : split) {
                    if (!Pattern.matches(timeCodePattern, timeCode)) {
                        throw new BizException(5, ("第" + (i + 4) + "排禁排时间" + timeCode + "超出课时方案"));
                    }
                }
            }
            //保存
            if (StrUtil.isNotBlank(timeCodes)) {
                String[] split = timeCodes.split("/");
                for (String timeCode : split) {
                    ruleRoomProhibits.add(new RuleRoomProhibit()
                            .setTaskId(importProhibit.getTaskId())
                            .setRoomId(roomMap.get(roomName))
                            .setTimeCode(timeCode)
                            .setSchoolId(importProhibit.getSchoolId())
                            .setTerm(importProhibit.getTerm())
                            .setCollegeId(importProhibit.getCollegeId())
                    );
                }
            }
        }

        if (importProhibit.getIsCoverage()) {
            ruleRoomProhibitService.lambdaUpdate().eq(RuleRoomProhibit::getTaskId, importProhibit.getTaskId()).eq(RuleRoomProhibit::getCollegeId,importProhibit.getCollegeId()).remove();
            ruleRoomProhibits = ruleRoomProhibits.stream().distinct().collect(Collectors.toList());
        } else {
            List<RuleRoomProhibit> existProhibit = ruleRoomProhibitService.lambdaQuery().eq(RuleRoomProhibit::getTaskId, importProhibit.getTaskId()).eq(RuleRoomProhibit::getCollegeId,importProhibit.getCollegeId()).list();
            ruleRoomProhibits = ruleRoomProhibits.stream()
                    .filter(o -> existProhibit.stream().noneMatch(p -> p.getTimeCode().equals(o.getTimeCode()) && p.getRoomId().equals(o.getRoomId())))
                    .distinct().collect(Collectors.toList());
        }
        if (CollUtil.isNotEmpty(ruleRoomProhibits)) {
            ruleRoomProhibitService.saveBatch(ruleRoomProhibits);
        }
    }

    /**
     * 导入教学班禁排
     *
     * @param importProhibit
     * @param read
     */
    public void toTeachingClassProhibit(ImportProhibit importProhibit, List<Map<String, Object>> read) {

        Map<String, Long> teachingClassMap = new HashMap<>();
        List<String> titleList = Arrays.asList("教学班名", "禁排时间", "优先排时间");
        List<RuleCourseProhibit> ruleCourseProhibits = new ArrayList<>();

        //判断模块是否符合要求
        boolean allColumnsMatch = titleList.containsAll(read.get(0).keySet());
        if (!allColumnsMatch) {
            throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
        }

        //获取全部教学班名
        List<String> teachingClassNames = read.stream()
                .map(o -> o.get("教学班名").toString())
                .distinct().collect(Collectors.toList());
        //获取全部教学班
        if (CollUtil.isNotEmpty(teachingClassNames)) {
            teachingClassMap = teachingClassService.lambdaQuery().eq(TeachingClass::getTaskId, importProhibit.getTaskId())
                    .in(TeachingClass::getTeachingClassName, teachingClassNames).ne(TeachingClass::getTeachingClassType, 3).list()
                    .stream().collect(Collectors.toMap(TeachingClass::getTeachingClassName, TeachingClass::getTeachingClassId));
        }
        //获取timeCode正则表达式
        String timeCodePattern = getTimeCodePattern(importProhibit.getSchoolId(), importProhibit.getTerm());

        //遍历
        for (int i = 0; i < read.size(); i++) {
            Map<String, Object> teachingClassProhibit = read.get(i);
            String teachingClassName = teachingClassProhibit.get("教学班名").toString();
            String timeCodes = teachingClassProhibit.get("禁排时间") == null ? "" : teachingClassProhibit.get("禁排时间").toString();
            String timeCodePossible = teachingClassProhibit.get("优先排时间") == null ? "" : teachingClassProhibit.get("优先排时间").toString();

            if (!teachingClassMap.containsKey(teachingClassName)) {
                throw new BizException(5, ("第" + (i + 4) + "行教学班名不存在" + teachingClassName));
            }
            //禁排时间
            if (StrUtil.isNotBlank(timeCodes)) {
                String[] split = timeCodes.split("/");
                for (String timeCode : split) {
                    if (!Pattern.matches(timeCodePattern, timeCode)) {
                        throw new BizException(5, ("第" + (i + 4) + "排禁排时间" + timeCode + "超出课时方案"));
                    }
                    ruleCourseProhibits.add(new RuleCourseProhibit()
                            .setTaskId(importProhibit.getTaskId())
                            .setTeachingClassId(teachingClassMap.get(teachingClassName))
                            .setTimeCode(timeCode).setFlag(2));
                }
            }
            //优先排时间
            if (StrUtil.isNotBlank(timeCodePossible)) {
                String[] split = timeCodePossible.split("/");
                for (String timeCode : split) {
                    if (!Pattern.matches(timeCodePattern, timeCode)) {
                        throw new BizException(5, ("第" + (i + 4) + "行优先排时间格式错误" + timeCode));
                    }
                    ruleCourseProhibits.add(new RuleCourseProhibit()
                            .setTaskId(importProhibit.getTaskId())
                            .setTeachingClassId(teachingClassMap.get(teachingClassName))
                            .setTimeCode(timeCode).setFlag(0));
                }
            }
        }
        List<RuleCourseProhibit> addList = new ArrayList<>();
        List<RuleCourseProhibit> updateList = new ArrayList<>();
        if (importProhibit.getIsCoverage()) {
            ruleCourseProhibitService.lambdaUpdate().eq(RuleCourseProhibit::getTaskId, importProhibit.getTaskId()).remove();
            addList = ruleCourseProhibits.stream().distinct().collect(Collectors.toList());
        } else {
            List<RuleCourseProhibit> existProhibit = ruleCourseProhibitService.lambdaQuery().eq(RuleCourseProhibit::getTaskId, importProhibit.getTaskId()).list();
            for (RuleCourseProhibit ruleCourseProhibit : ruleCourseProhibits) {
                Optional<RuleCourseProhibit> isCoverage = existProhibit.stream().filter(o -> o.getTimeCode().equals(ruleCourseProhibit.getTimeCode()) && o.getTeachingClassId().equals(ruleCourseProhibit.getTeachingClassId())).findFirst();
                if (isCoverage.isPresent()) {
                    if (!ruleCourseProhibit.getFlag().equals(isCoverage.get().getFlag())) {
                        updateList.add(isCoverage.get().setFlag(ruleCourseProhibit.getFlag()));
                    }
                } else {
                    addList.add(ruleCourseProhibit);
                }
            }
        }
        if (CollUtil.isNotEmpty(addList)) {
            ruleCourseProhibitService.saveBatch(addList);
        }
        if (CollUtil.isNotEmpty(updateList)) {
            ruleCourseProhibitService.updateBatchById(updateList);
        }
    }

    /**
     * 导入教师禁排
     *
     * @param importProhibit
     * @param read
     */
    public void toTeacherProhibit(ImportProhibit importProhibit, List<Map<String, Object>> read) {
        Map<String, Long> teacherMap = new HashMap<>();
        List<String> titleList = Arrays.asList("任课教师工号", "优先排时间", "固排时间", "禁排时间");
        List<RuleTeacherTime> ruleTeacherTimes = new ArrayList<>();
        //判断模块是否符合要求
        boolean allColumnsMatch = titleList.containsAll(read.get(0).keySet());
        if (!allColumnsMatch) {
            throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
        }

        //获取全部教师工号
        List<String> teacherCodes = read.stream()
                .map(o -> o.get("任课教师工号").toString())
                .distinct().collect(Collectors.toList());
        //获取全部教师
        if (CollUtil.isNotEmpty(teacherCodes)) {
            teacherMap = teacherService.lambdaQuery().eq(Teacher::getSchoolId, importProhibit.getSchoolId())
                    .eq(Teacher::getTerm, importProhibit.getTerm())
                    .in(Teacher::getBaseTeacherId, teacherCodes).list()
                    .stream().collect(Collectors.toMap(Teacher::getBaseTeacherId, Teacher::getTeacherId));
        }
        //获取timeCode正则表达式
        String timeCodePattern = getTimeCodePattern(importProhibit.getSchoolId(), importProhibit.getTerm());

        //遍历
        for (int i = 0; i < read.size(); i++) {
            Map<String, Object> teacherProhibit = read.get(i);
            String teacherCode = teacherProhibit.get("任课教师工号").toString();
            String timeCodePossible = teacherProhibit.get("优先排时间").toString();
            String timeCodeProhibit = teacherProhibit.get("禁排时间").toString();

            if (!teacherMap.containsKey(teacherCode)) {
                throw new BizException(5, ("第" + (i + 4) + "行任课教师工号不存在" + teacherCode));
            }
            if (StrUtil.isNotBlank(timeCodePossible)) {
                String[] split = timeCodePossible.split("/");
                for (String timeCode : split) {
                    if (!Pattern.matches(timeCodePattern, timeCode)) {
                        throw new BizException(5, ("第" + (i + 4) + "排禁排时间" + timeCode + "超出课时方案"));
                    }
                }
            }

            if (StrUtil.isNotBlank(timeCodeProhibit)) {
                String[] split = timeCodeProhibit.split("/");
                for (String timeCode : split) {
                    if (!Pattern.matches(timeCodePattern, timeCode)) {
                        throw new BizException(5, ("第" + (i + 4) + "排禁排时间" + timeCode + "超出课时方案"));
                    }
                }
            }
            //保存
            if (StrUtil.isNotBlank(timeCodePossible)) {
                String[] splitPossible = timeCodePossible.split("/");
                for (String timeCode : splitPossible) {
                    ruleTeacherTimes.add(new RuleTeacherTime()
                            .setTaskId(importProhibit.getTaskId())
                            .setTeacherId(teacherMap.get(teacherCode))
                            .setTimeCode(timeCode)
                            .setFlag(0)
                            .setSchoolId(importProhibit.getSchoolId())
                            .setTerm(importProhibit.getTerm())
                            .setCollegeId(importProhibit.getCollegeId()));
                }
            }

            if (StrUtil.isNotBlank(timeCodeProhibit)) {
                String[] splitProhibit = timeCodeProhibit.split("/");
                for (String timeCode : splitProhibit) {
                    ruleTeacherTimes.add(new RuleTeacherTime()
                            .setTaskId(importProhibit.getTaskId())
                            .setTeacherId(teacherMap.get(teacherCode))
                            .setTimeCode(timeCode)
                            .setFlag(2)
                            .setSchoolId(importProhibit.getSchoolId())
                            .setTerm(importProhibit.getTerm())
                            .setCollegeId(importProhibit.getCollegeId()));
                }
            }
        }
        List<RuleTeacherTime> addList = new ArrayList<>();
        List<RuleTeacherTime> updateList = new ArrayList<>();
        if (importProhibit.getIsCoverage()) {
            ruleTeacherTimeService.lambdaUpdate().eq(RuleTeacherTime::getTaskId, importProhibit.getTaskId()).eq(RuleTeacherTime::getCollegeId,importProhibit.getCollegeId()).remove();
            addList = ruleTeacherTimes.stream().distinct().collect(Collectors.toList());
        } else {
            List<RuleTeacherTime> existProhibit = ruleTeacherTimeService.lambdaQuery().eq(RuleTeacherTime::getTaskId, importProhibit.getTaskId()).eq(RuleTeacherTime::getCollegeId,importProhibit.getCollegeId()).list();
            //timecode teacher 相同则为更新  否则为新增
            for (RuleTeacherTime ruleTeacherTime : ruleTeacherTimes) {
                Optional<RuleTeacherTime> isCoverage = existProhibit.stream().filter(o -> o.getTimeCode().equals(ruleTeacherTime.getTimeCode()) && o.getTeacherId().equals(ruleTeacherTime.getTeacherId())).findFirst();
                if (isCoverage.isPresent()) {
                    if (!ruleTeacherTime.getFlag().equals(isCoverage.get().getFlag())) {
                        updateList.add(isCoverage.get().setFlag(ruleTeacherTime.getFlag()));
                    }
                } else {
                    addList.add(ruleTeacherTime);
                }
            }
        }

        if (CollUtil.isNotEmpty(addList)) {
            ruleTeacherTimeService.saveBatch(addList);
        }
        if (CollUtil.isNotEmpty(updateList)) {
            ruleTeacherTimeService.updateBatchById(updateList);
        }
    }

    /**
     * 获取最大节次的时间  并转化为正则表达式
     *
     * @param schoolId
     * @param term
     * @return
     */
    public String getTimeCodePattern(String schoolId, String term) {
        List<RuleWeekDay> weekDays = this.getWeekDays(schoolId, term);
        OptionalInt maxPeriodSchemesSize = weekDays.stream()
                .mapToInt(day -> day.getPeriodSchemes().size())
                .max();

        //最大周次
        int maxWeek = 7;
        //最大节次
        int maxPeriod = maxPeriodSchemesSize.orElse(0);
        // 生成周次的正则表达式
        String weekRegex = maxWeek < 10 ? "(0[1-" + maxWeek + "])" : "(0[1-9]|1[0-" + (maxWeek - 10) + "])";
        // 生成节次的正则表达式
        String periodRegex = maxPeriod < 10 ? "(0[1-" + maxPeriod + "])" : "(0[1-9]|1[0-" + (maxPeriod - 10) + "])";
        return "^" + weekRegex + periodRegex + "$";
    }

    public void toCollegeRoom(ImportProhibit importProhibit, List<Map<String, Object>> read) {
        List<String> titleList = Arrays.asList("院系名", "上课场地");
        List<CollegeRoom> collegeRooms = new ArrayList<>();

        //判断模块是否符合要求
        boolean allColumnsMatch = titleList.containsAll(read.get(0).keySet());
        if (!allColumnsMatch) {
            throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
        }

        //获取院系
        Map<String, String> collegeMap = majorMapper.getCollegeByTaskId(importProhibit.getTaskId())
                .stream().collect(Collectors.toMap(CollegeDto::getCollegeName, CollegeDto::getCollegeId));
        //获取全部教室名
        Map<String, Room> roomMap = roomService.lambdaQuery().eq(Room::getSchoolId, importProhibit.getSchoolId())
                .eq(Room::getTerm, importProhibit.getTerm()).list()
                .stream().collect(Collectors.toMap(Room::getRoomName, o -> o));

        //遍历
        for (int i = 0; i < read.size(); i++) {
            Map<String, Object> collegeRoomMap = read.get(i);
            String collegeName = collegeRoomMap.get("院系名").toString();
            String roomName = collegeRoomMap.get("上课场地").toString();

            if (!collegeMap.containsKey(collegeName)) {
                throw new BizException(5, ("第" + (i + 4) + "行院系名不存在" + collegeName));
            }
            if (StrUtil.isNotBlank(roomName)) {
                String[] split = roomName.split("/");
                for (String roomNameSign : split) {
                    if (!roomMap.containsKey(roomNameSign)) {
                        throw new BizException(5, ("第" + (i + 4) + "行上课场地名" + roomNameSign + "不存在"));
                    }
                    collegeRooms.add(new CollegeRoom()
                            .setTaskId(importProhibit.getTaskId())
                            .setCollegeId(collegeMap.get(collegeName))
                            .setRoomId(roomMap.get(roomNameSign).getRoomId())
                            .setRoomName(roomNameSign)
                            .setBuildingName(roomMap.get(roomNameSign).getBuildingName()));
                }
            }
        }
        if (importProhibit.getIsCoverage()) {
            collegeRoomService.lambdaUpdate().eq(CollegeRoom::getTaskId, importProhibit.getTaskId()).remove();
            collegeRooms = collegeRooms.stream().distinct().collect(Collectors.toList());
        } else {
            List<CollegeRoom> existCollegeRoom = collegeRoomService.lambdaQuery().eq(CollegeRoom::getTaskId, importProhibit.getTaskId()).list();
            collegeRooms = collegeRooms.stream()
                    .filter(o -> existCollegeRoom.stream().noneMatch(p -> p.getCollegeId().equals(o.getCollegeId()) && p.getRoomId().equals(o.getRoomId())))
                    .distinct().collect(Collectors.toList());
        }
        if (CollUtil.isNotEmpty(collegeRooms)) {
            collegeRoomService.saveBatch(collegeRooms);
        }
    }


    @Override
    public void conversionCourseProhibit(ImportProhibit importProhibit, MultipartFile file, ServletOutputStream out) {
        // I don't want to do this shit.
        try {
            InputStream inputStream = file.getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream);
            List<Map<String, Object>> read = reader.read(1, 2, reader.getRowCount());
            if (CollUtil.isEmpty(read)) {
                throw new BizException(5, "导入文件数据为空");
            }

            List<String> titleList = Arrays.asList("课程名称", "固排禁排优排要求");
            //判断模块是否符合要求
            boolean allColumnsMatch = titleList.containsAll(read.get(0).keySet());
            if (!allColumnsMatch) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }
            //获取全部课程名称
            List<String> courseNames = read.stream()
                    .map(o -> o.get("课程名称").toString())
                    .distinct().collect(Collectors.toList());
            //获取全部课程 对应教学班名
            Map<String, List<GroupObject<String, String>>> teachingClassNameMap = new HashMap<>();
            if (CollUtil.isNotEmpty(courseNames)) {
                teachingClassNameMap = teachingClassMapper.getTeachingClassNameByCourseName(importProhibit.getTaskId(), courseNames).stream()
                        .collect(Collectors.groupingBy(GroupObject::getField));
            }

            List<List<Object>> rows = new ArrayList<>();
            for (int i = 0; i < read.size(); i++) {
                Map<String, Object> courseProhibit = read.get(i);
                String courseName = courseProhibit.get("课程名称").toString();
                String prohibit = courseProhibit.get("固排禁排优排要求").toString();
                //待生成 优先排字符串
                StringJoiner timeCodePossible = new StringJoiner("/");
                //待生成 禁排字符串
                StringJoiner timeCodeProhibit = new StringJoiner("/");

                //将固排禁排优排要求 转化为教学班禁排模板格式
                for (String timeCodeString : prohibit.split("\\|")) {
                    if (timeCodeString.contains("优排")) {
                        timeCodeString = timeCodeString.replaceAll("优排", "");
                        for (String oneTimeCode : timeCodeString.split(",")) {
                            if (Pattern.matches("^[0-9]{2}$", oneTimeCode)) {
                                String format = String.format("%02d%02d", Integer.parseInt(oneTimeCode) / 10, Integer.parseInt(oneTimeCode) % 10);
                                timeCodePossible.add(format);
                            }
                        }
                    }

                    if (timeCodeString.contains("禁排")) {
                        timeCodeString = timeCodeString.replaceAll("禁排", "");
                        for (String oneTimeCode : timeCodeString.split(",")) {
                            if (Pattern.matches("^[0-9]{2}$", oneTimeCode)) {
                                String format = String.format("%02d%02d", Integer.parseInt(oneTimeCode) / 10, Integer.parseInt(oneTimeCode) % 10);
                                timeCodeProhibit.add(format);
                            }
                        }
                    }
                }

                //一个教学班构造一行数据
                teachingClassNameMap.getOrDefault(courseName, new ArrayList<>()).forEach(groupObject -> {
                    rows.add(ListUtil.toList(groupObject.getNum(), timeCodePossible.toString(), timeCodeProhibit.toString()));
                });
            }
            //写入到输出流
            ExcelFormatUtil.writeRowsToExcel(rows, "UploadTeachingClassProhibit.xlsx", 3, out);
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
